package com.ck.ips.service.impl.program;

import com.alibaba.fastjson.JSON;
import com.ck.common.model.MonitorDataFile;
import com.ck.core.constant.DateFormatConstant;
import com.ck.core.constant.ElasticsearchConstant;
import com.ck.core.exception.ServiceException;
import com.ck.core.util.DateUtils;
import com.ck.ips.core.config.CustomProperties;
import com.ck.ips.dao.program.MonitorDataFileMapper;
import com.ck.ips.service.ElasticsearchService;
import com.ck.ips.service.program.MonitorDataFileService;
import io.searchbox.core.SearchResult;
import io.searchbox.core.search.aggregation.MetricAggregation;
import io.searchbox.core.search.aggregation.SumAggregation;
import io.searchbox.core.search.aggregation.TermsAggregation;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.index.query.*;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.sum.SumAggregationBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.text.ParseException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author dxy
 * @date 2019/5/8 11:17
 */
@Service(value = "monitorDataFileService")
public class MonitorDataFileServiceImpl implements MonitorDataFileService {
	@Autowired
	private MonitorDataFileMapper monitorDataFileMapper;
	@Autowired
	private ElasticsearchService elasticsearchService;
	@Autowired
	private CustomProperties customProperties;
	/**
	 * 批量插入
	 *
	 * @param monitorDataFileList List<MonitorDataFile>
	 */
	@Override
	public void insertBatch(List<MonitorDataFile> monitorDataFileList) {
		if (CollectionUtils.isNotEmpty(monitorDataFileList)) {
			monitorDataFileMapper.insertBatch(monitorDataFileList);
		}
	}

	/***
	 * 获取素材的实时播放次数和播放时长
	 *
	 * @param deviceCode     终端编码
	 * @return String(JSON格式字符串)
	 * @throws ParseException
	 * @throws IOException
	 * @throws ServiceException
	 */
	@Override
	public String getFileRealTimePlayNumDuration(String deviceCode) throws ParseException, IOException, ServiceException {
		if (StringUtils.isBlank(deviceCode)) {
			throw new ServiceException("输入参数不能为空");
		}
		//获取昨天的日期
		String date = DateUtils.getPastDay(DateFormatConstant.YESTERDAY, DateFormatConstant.DATE_YEAR_MONTH_DAY);

		//索引名称
		String indexName = customProperties.getBusinessType() + ElasticsearchConstant.INDEX_MONITOR_DATA_FILE;
		//索引类型
		String indexType = "";

		/** 查询条件 */
		//查询索引中的所有数据
		MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
		//多条件查询
		BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
		boolQueryBuilder.must(matchAllQueryBuilder);

		//一天的开始时间
		Long startTime = DateUtils.stringTimeToLongTimeStamp(date + " " + DateFormatConstant.MIN_HOUR_MINUTE_SECOND_MILLISECOND, DateFormatConstant.YEAR_MONTH_DAY_HMS_SSS);
		//当前时间
		Long endTime = System.currentTimeMillis();
		//时间
		RangeQueryBuilder programPlayStartTimeQueryBuilder = QueryBuilders.rangeQuery(ElasticsearchConstant.FILE_PLAY_START_TIME).from(startTime).to(endTime).format(ElasticsearchConstant.EPOCH_MILLIS);
		boolQueryBuilder.must(programPlayStartTimeQueryBuilder);

		//终端编码
		MatchPhraseQueryBuilder programVersionDeviceCodeQueryBuilder = QueryBuilders.matchPhraseQuery(ElasticsearchConstant.DEVICE_CODE, deviceCode);
		boolQueryBuilder.must(programVersionDeviceCodeQueryBuilder);

		/** 聚合计算 */
		//按programVersion分组
		TermsAggregationBuilder programVersionAggregationBuilder = AggregationBuilders.terms(ElasticsearchConstant.GROUP_BY_PROGRAM_VERSION).field(ElasticsearchConstant.PROGRAM_VERSION_KEYWORD).size(Integer.MAX_VALUE);

		//按fileNameURL分组
		TermsAggregationBuilder fileNameURLAggregationBuilder = AggregationBuilders.terms(ElasticsearchConstant.GROUP_BY_FILE_NAME_URL).field(ElasticsearchConstant.FILE_NAME_URL_KEYWORD).size(Integer.MAX_VALUE);

		//计算素材累计播放时长
		SumAggregationBuilder playDurationSumAggregationBuilder = AggregationBuilders.sum(ElasticsearchConstant.PLAY_DURATION_SUM).field(ElasticsearchConstant.PLAY_DURATION);

		fileNameURLAggregationBuilder.subAggregation(playDurationSumAggregationBuilder);
		programVersionAggregationBuilder.subAggregation(fileNameURLAggregationBuilder);

		//从ES查询数据
		SearchResult searchResult = elasticsearchService.doSearch(indexName, indexType, null, boolQueryBuilder, programVersionAggregationBuilder);
		//错误信息
		String errorMessage = searchResult.getErrorMessage();

		Map<String, Map<String, Long>> resultMap = new HashMap<>();

		//没有错误
		if (StringUtils.isBlank(errorMessage)) {
			MetricAggregation metricAggregation = searchResult.getAggregations();
			//获取programVersion分组的Buckets
			TermsAggregation programVersionTermsAggregation = metricAggregation.getTermsAggregation(ElasticsearchConstant.GROUP_BY_PROGRAM_VERSION);
			List<TermsAggregation.Entry> programVersionBuckets = programVersionTermsAggregation.getBuckets();

			for (TermsAggregation.Entry programVersionEntry : programVersionBuckets) {
				//节目版本号
				String programVersion = programVersionEntry.getKey();
				//获取fileNameURL分组的Buckets
				TermsAggregation fileNameURLTermsAggregation = programVersionEntry.getTermsAggregation(ElasticsearchConstant.GROUP_BY_FILE_NAME_URL);
				List<TermsAggregation.Entry> fileNameURLBuckets = fileNameURLTermsAggregation.getBuckets();

				for (TermsAggregation.Entry fileNameURLEntry : fileNameURLBuckets) {
					Map<String, Long> playNumDurationMap = new HashMap<>();
					//文件名称URL
					String fileNameURL = fileNameURLEntry.getKey();
					//素材播放次数(素材的分组数就是素材的播放次数)
					Long playNumSum = fileNameURLEntry.getCount();
					if (playNumSum == null) {
						playNumSum = 0L;
					}
					playNumDurationMap.put(ElasticsearchConstant.PLAY_NUM_COUNT, playNumSum);

					//素材累计播放时长
					SumAggregation playDurationSumAggregation = fileNameURLEntry.getSumAggregation(ElasticsearchConstant.PLAY_DURATION_SUM);
					Double playDurationSum = playDurationSumAggregation.getSum();
					if (playDurationSum == null) {
						playDurationSum = 0D;
					}
					playNumDurationMap.put(ElasticsearchConstant.PLAY_DURATION_SUM, playDurationSum.longValue());
					String key = programVersion + ElasticsearchConstant.SEPARATOR + fileNameURL;
					resultMap.put(key, playNumDurationMap);
				}
			}
		} else {
			//如果有错误信息，将错误信息抛给调用方法者，由调用者处理错误信息
			throw new ServiceException(errorMessage);
		}
		return JSON.toJSONString(resultMap);
	}
}
